import 'dart:async';
import 'dart:io';

import 'package:async_pool/async_pool.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:wechat_decode/model/decode_async_task.dart';
import 'package:wechat_decode/model/decode_model.dart';
import 'package:wechat_decode/utils/decode_util.dart';

part 'decode_progress_state.g.dart';

IsolateExecutor? _isolateExecutor;

/// 解码进度
@Riverpod(keepAlive: true)
class DecodeProgressNotifier extends _$DecodeProgressNotifier {
  static Set<CompletableIsolate<DecodeAsyncTask>>? _futures;
  bool _canceling = false;
  bool _traverseDir = false;

  @override
  WxDecodeProgress build() {
    return WxDecodeProgress();
  }

  /// 递增任务数
  void incrementCurrentAndSetPath(String path) {
    state.current++;
    state.printout = path;
    ref.notifyListeners();
  }

  /// 开始任务
  void task({required String input, required String output, bool isCopy = false}) async {
    state.isComputed = false;
    state.total = 0;
    state.current = 0;
    state.printout = '';
    _canceling = false;
    _traverseDir = false;
    _futures = null;
    ref.notifyListeners();
    await _runTask(input, output, isCopy);
    state.isComputed = true;
    state.printout = '执行完毕';
    ref.notifyListeners();
  }

  /// 取消任务
  void cancelTask() async {
    _canceling = true;
    // 检测遍历目录是否停止
    await Future.doWhile(() async {
      if (!_traverseDir) {
        return _traverseDir;
      }
      await Future.delayed(const Duration(milliseconds: 100));
      return _traverseDir;
    });
    // 停止多线程
    // await Future.microtask(() async {
    //   _futures?.forEach((element) {
    //     element.cancel();
    //   });
    // });
    _isolateExecutor?.shutdown();
    _futures?.clear();
    state.isComputed = true;
    ref.notifyListeners();
  }

  /// 运行任务
  Future<void> _runTask(String input, String output, bool isCopy) async {
    List<DecodeAsyncTask> tasks = [];
    _traverseDir = true;
    try {
      var stream = Directory(input).list(recursive: true, followLinks: false);
      await for (var element in stream) {
        if (_canceling) {
          return;
        }
        if (element is File && (isCopy || element.path.endsWith('.dat'))) {
          state.total++;
          tasks.add(DecodeAsyncTask(input, element.path, output, isCopy));
          ref.notifyListeners();
        }
      }
    } finally {
      _traverseDir = false;
    }
    ref.notifyListeners();
    // 如果已经取消，则不加入任务
    if (_canceling) {
      return;
    }
    // 初始化线程池
    _isolateExecutor = IsolateExecutor(
      maximumPoolSize: Platform.numberOfProcessors,
      keepActiveTime: 5,
    );
    for (var param in tasks) {
      if (_canceling) {
        break;
      }
      var completableIsolate = CompletableIsolate.runAsync((task) async {
        task.output = await DecodeUtil.convert(task.root, task.input, task.output, task.isCopy);
        return task;
      }, param, isolateExecutor: _isolateExecutor);
      completableIsolate.then((value) {
        var data = value as DecodeAsyncTask;
        state.printout = '${data.input} -> ${data.output}';
      });
      completableIsolate.whenComplete(() {
        _futures?.remove(completableIsolate);
        state.current++;
        ref.notifyListeners();
      });
      (_futures ??= {}).add(completableIsolate);
    }

    await CompletableIsolate.join(_futures!);
  }
}
